#**************************************************************************
# * Copyright (C) 2012-2021  Unisound
# *
# * This program is free software; you can redistribute it and/or modify
# * it under the terms of the GNU General Public License as published by
# * the Free Software Foundation; either version 2 of the License, or
# * any later version.
# *
# * This program is distributed in the hope that it will be useful,
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# * GNU General Public License for more details.
# *
# * You should have received a copy of the GNU General Public License along
# * with this program; if not, write to the Free Software Foundation, Inc.,
# * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# **************************************************************************
# *
# * Description : Top Makefile
# * Author      : yzs.unisound.com
# * Date        : 2021.03.01
# *
# **************************************************************************/

all: build

# absolute path
CURDIR          := $(shell pwd)
Q               := @
SUBDIR          := $(obj)
CCFLAGS         += $(CFLAG)

ifeq ($(quiet),silent_)
silent := -s
endif

ifneq (,$(wildcard $(CURDIR)/uniconfig.mk))
include $(CURDIR)/uniconfig.mk
endif
#==================================================================================#

CROSS_COMPILE   = /opt/us513/bin/csky-abiv2-elf-
AR              = $(CROSS_COMPILE)ar
AS              = $(CROSS_COMPILE)as
CC              = $(CROSS_COMPILE)gcc
LD              = $(CROSS_COMPILE)ld
OBJCOPY         = $(CROSS_COMPILE)objcopy
OBJDUMP         = $(CROSS_COMPILE)objdump
NM              = $(CROSS_COMPILE)nm
STRIP           = $(CROSS_COMPILE)strip
READELF         = $(CROSS_COMPILE)readelf -a

SHELL           = /bin/bash

#==================================================================================#

#=================================================================================#
# Flags Configurations
#---------------------------------------------------------------------------------#
#       Optimization options (add to CCFLAGS ):
#       -O0 -g  = Level 0       no optimization, debug info is enabled
#       -O1     = Level 1       (incompatible with -g option (gebug info))
#       -O2     = Level 2       (incompatible with -g option)
#       -O3     = Level 3       (incompatible with -g option)
#       -Os     = Level s       (incompatible with -g option)
#---------------------------------------------------------------------------------#
# The pre-processor and compiler options.
CCFLAGS    		 += -Os

GCCVERSION = $(shell $(CC) --version | grep csky-abiv2-elf-gcc)
ifeq "$(GCCVERSION)" "csky-abiv2-elf-gcc (C-SKY Tools V3.10.15 Minilibc abiv2 B20190929) 6.3.0"
else
	_VERSION=$(GCCVERSION)
	_ERR_FLAG="Version error!"
endif

CCFLAGS        += -mcpu=ck804ef -Wpointer-arith -Wundef -Wall -Wundef \
                  -Wstrict-prototypes -pipe -fno-builtin -fno-strict-aliasing\
                  -fstrict-volatile-bitfields -mhard-float

ASFLAGS         = -mcpu=ck804ef -Wa,--defsym=ck804=1 -EL -mhard-float

# The git version of mcu app
APP_VERSION    := "v1.0.14.5_1mb"
CCFLAGS        += -DAPP_VERSION=\"$(APP_VERSION)\"
ASFLAGS        += -DAPP_VERSION=\"$(APP_VERSION)\"

# The build time of mcu app
BUILD_TIME      = $(shell date +"%Y-%m-%d,\ %H:%M:%S")
CCFLAGS        += -DBUILD_TIME=\"$(BUILD_TIME)\"

# The options used in linking as well as in any direct use of ld.
LDFLAGS         = -EL

# The options used in archive as well as in any direct use of ar.
ARFLAGS         = -rcs

CCFLAGS        += -ffunction-sections -nostdlib
LDFLAGS        += --gc-sections

CCFLAGS        += -D__WORDSIZE=32
#---------------------------------------------------------------------------------#

INCLUDE_DIR    += include/soc/include
INCLUDE_DIR    += include/utility/libdsp
INCLUDE_DIR    += include/utility/libc
INCLUDE_DIR    += include/utility
INCLUDE_DIR    += include
INCLUDE_DIR    += lvp/common
INCLUDE_DIR    += lvp/common/player/mp3_player
INCLUDE_DIR    += lvp/vui/kws
INCLUDE_DIR    += app/ivm app/ivm/user

LIBS            = -lboot -lhal -lbase -lkws -lual-osal
LIBS           += -lm -lc
LIBS           += -lgcc
LIB_DIR         = lib
LIB_DIR        += $(shell $(CC) -print-file-name=ck803)/hard-fp
LIB_DIR        += $(shell $(CC) -print-file-name=ck803)/../../../../../csky-elfabiv2/lib/ck803/hard-fp/

# The directories in which header files reside.
# If not specified, only the current directory will be serached.
INCLUDE_FLAGS   = $(addprefix -I , $(INCLUDE_DIR))
LIB_FLAGS       = $(addprefix -L , $(LIB_DIR))

#---------------------------------------------------------------------------------#

ASFLAGS        += $(INCLUDE_FLAGS)
CCFLAGS        += $(INCLUDE_FLAGS)
LDFLAGS        += $(LIB_FLAGS) $(LIBS)

#=================================================================================#
# Source List

-include lvp/Makefile
-include 3rdparty/Makefile
-include app/Makefile

ifdef CONFIG_MCU_COMPILE_MATH_LIB_FROM_SOURCE_CODE
$(ckdsp_objs):EXTRA_FLAGS := -mhard-float -D__FPU_PRESENT -fdata-sections -Wl,--gc-sections -DUNALIGNED_SUPPORT_DISABLE -DCSKY_SIMID
endif

lib_objs         =  $(common_objs) $(lvp_objs) $(kws_objs) $(uni_kws_objs) $(ctc_decoder_objs) $(vpr_objs) $(app_objs)

ifeq ($(CONFIG_USE_MP3), y)
lib_objs += $(mp3_objs)
CCFLAGS += -DUSE_MP3
endif
mcu_objs        = $(subst ",,$(lib_objs))
all_objs        = $(mcu_objs) $(lvp_objs)
all_deps        = $(subst .o,.d,$(all_objs))

#=================================================================================#
# Build Rules

.PHONY: clean export help

# Build objects
build: prepare  output/uni_app.elf output/uni_app.info.txt output/uni_app.dump.txt
build: output/mcu.bin checkbin

prepare:
	@echo [Preparing lvp ...]
	@mkdir -p output
	@mkdir -p tmp_objs
	@$(AR) -x lib/libboot.a
	@$(AR) -x lib/libhal.a
	@$(AR) -x lib/libbase.a
	@mv *.o tmp_objs/
	@$(CC) $(CCFLAGS) $(EXTRA_FLAGS) -E -x assembler-with-cpp -P -o output/uni_app.ld ./link.ld

ifdef snpu_objs
lib/libsnpu.a: $(snpu_objs)
	@echo [$(AR) archiving $@]
	@$(AR) $(ARFLAGS) $@ $^
endif

ifdef ckdsp_objs
lib/libcsky_dsp.a: $(ckdsp_objs)
	@echo [$(AR) archiving $@]
	@$(AR) $(ARFLAGS) $@ $^
endif

output/uni_app.elf: output/uni_app.ld $(all_objs)
	@echo [$(LD) linking $@]
	@$(LD) -o $@ -T $^ $(LDFLAGS)
	@size $@

#---------------------------------------------------------------------------------#

output/uni_app.dump.txt: output/uni_app.elf
	@echo [$(OBJDUMP) disassemble $^]
	@$(OBJDUMP) -Sa $^ > $@

output/uni_app.info.txt: output/uni_app.elf
	@echo [$(READELF) dump sections $^]
	@$(READELF) $^ > $@

export: output/uni_app.elf output/uni_app.bin
	@echo "[Exporting $^]"
	@cp -f $^ ../output

checkbin:
	@echo
	@ls -l output/* | awk '{printf "%-25s:\t %-8sByte\n", $$9, $$5 }'

#---------------------------------------------------------------------------------#

ifneq ($(MAKECMDGOALS), )
    NOT_INCLUDE_DEP = true
endif
ifneq ($(NOT_INCLUDE_DEP), true)
    -include $(all_deps)
endif

#---------------------------------------------------------------------------------#
# Common Build Rules
%.d:%.c
    ifeq (${_ERR_FLAG},"Version error!")
	@echo
	@echo "________________________________/ERROR\\___________________________________"
	@echo "|Now compiler version :                                                  |"
	@echo "|${GCCVERSION}"
	@echo "|                                                                        |"
	@echo "|Version error!                                                          |"
	@echo "|                                                                        |"
	@echo "|The right version :                                                     |"
	@echo "|csky-abiv2-elf-gcc (C-SKY Tools V3.10.15 Minilibc abiv2 B20190929) 6.3.0 |"
	@echo "|________________________________________________________________________|"
	@echo
	@killall make
    endif
	@echo [$(CC) creating $@]
	@$(CC) $(CCFLAGS) -M $< > $@.$$$$;\
	sed 's,\(.*\)\.o[ :]*,$(shell dirname $@)/\1.o $@ : ,g' <$@.$$$$ > $@;\
	$(RM) $@.$$$$

%.d:%.S
	@echo [$(CC) creating $@]
	@$(CC) $(CCFLAGS) -M $< > $@.$$$$;\
	sed 's,\(.*\)\.o[ :]*,$(shell dirname $@)/\1.o $@ : ,g' <$@.$$$$ > $@;\
	$(RM) $@.$$$$

%.o:%.c
	@echo [$(CC) compiling $@]
	@$(CC) $(CCFLAGS) $(EXTRA_FLAGS) -c $< -o $@

%.o:%.S
	@echo [$(CC) assembling $@]
	@$(CC) $(ASFLAGS) -c $< -o $@


clean:
	@rm -f $(all_objs) $(all_deps) $(snpu_objs) $(ckdsp_objs)
	@rm -rf output
	@echo [Clean all]

distclean: clean
	@-make -C $(SUBDIR) clean
	@-find . -name *.d | xargs rm
	@-rm -f include/autogenerated_config.h
	@-rm -f include/autoconf.h

help:
	@echo 'Generic Makefile for C/C++ Programs (GNU/linux makefile) version 0.1'
	@echo 'Copyright (C) 2012-2021 Unisound AI Technology Co., Ltd.
	@echo 'ALL RIGHTS RESERVED!'
	@echo
	@echo 'Usage: make [TARGET]'
	@echo 'TARGETS:'
	@echo '  all       compile and create elf files(.elf)'
	@echo '  clean     clean all objects and the executable file.'
	@echo '  help      print this message.'
	@echo


#---------------------------------------------------------------------------------#
#   US513 flash bin 文件组成
#
#  * -------------------------------------------
#  * |            |                 |          |
#  * |   struct   |      struct     | bin body |
#  * | bin_header |   stage1_info   |          |
#  * |            |                 |          |
#  * -------------------------------------------
#
# #define BIN_HEADER_MAGIC 0x484E4942
#  struct bin_header {
#      unsigned int magic;                // 'B' 'I' 'N' 'H'
#      unsigned int medium_magic;         // 0xaa55aa55 for nor; 0xbb55bb55 for nand
#      unsigned int version;              // 0x00000001
#  };
#
#  struct stage1_info_v1 {
#      unsigned int stage1_addr;
#      unsigned int stage1_size;
#      unsigned int stage1_load_addr;
#  };
#
#  bin body : stage1 + stage2
#
BOOTLOADER_MAGIC_NOR='AA55AA55'
BIN_HEADER_MEDIUM_MAGIC=$(BOOTLOADER_MAGIC_NOR)
BIN_HEADER_MAGIC_PRE='0x484E4942'
BIN_HEADER_MAGIC=$(shell ./tools/scripts/switch_endian.sh $(shell printf "%08x" $(BIN_HEADER_MAGIC_PRE)))
BIN_HEADER_VERSION_PRE='0x00000001'
BIN_HEADER_VERSION=$(shell ./tools/scripts/switch_endian.sh $(shell printf "%08x" $(BIN_HEADER_VERSION_PRE)))

STAGE1_ADDR_PRE='0x00000000'
STAGE1_ADDR=$(shell ./tools/scripts/switch_endian.sh $(shell printf "%08x" $(STAGE1_ADDR_PRE)))
STAGE1_SIZE_PRE=$(shell printf "0x%08x" $(shell grep "CONFIG_STAGE1_SRAM_SIZE" include/soc/include/soc_config.h | head -n 1 | awk '{print $$3}'))
STAGE1_SIZE=$(shell ./tools/scripts/switch_endian.sh $(shell printf "%08x" $(STAGE1_SIZE_PRE)))
STAGE1_LOAD_ADDR_PRE=$(shell printf "0x%08x" $(shell grep "CONFIG_STAGE1_DRAM_BASE" include/soc/include/soc_config.h | head -n 1 | awk '{print $$3}'))
STAGE1_LOAD_ADDR=$(shell ./tools/scripts/switch_endian.sh $(shell printf "%08x" $(STAGE1_LOAD_ADDR_PRE)))

MAGIC_NUM := 4
SUFFIX = ".bin"
BOOT_HEAD_NOR=$(BIN_HEADER_MAGIC)$(BIN_HEADER_MEDIUM_MAGIC)$(BIN_HEADER_VERSION)$(STAGE1_ADDR)$(STAGE1_SIZE)$(STAGE1_LOAD_ADDR)
BOOT_HEAD_LEN=24

ORIGIN_FILE = "$(ORIGIN_FILED)$(SUFFIX)"

SOC_STAGE1_SIZE=$(STAGE1_SIZE_PRE)
# 生成经过CRC校验的bin文件
# $1 name (spi_nor/spi_nand/......)
# $2 boot_head
# S3 header_len
# $4 stage1备份的数量，spi_nand备份4份
# $5 目标文件的名称
define CREATE_BIN
	@mkdir -p output
	@sed '1i$2' output/TEMP_FILE1 > TEMP_FILE2
	@xxd -r -c4 -p TEMP_FILE2 > tmp.bin
	@./loader_write tmp.bin output/$5 $3 $(SOC_STAGE1_SIZE) $4
	@rm -rf tmp.bin
endef

define CLEAN_TMP_FILE
	@rm -rf output/TEMP_FILE1 TEMP_FILE2 $@
endef

output/mcu.bin: output/uni_app.elf
	@echo [$(OBJCOPY) dump $@]
	@$(OBJCOPY) -O binary --remove-section=.dummy_for_stage1_text_place_hold --remove-section=.dummy_for_stage2_text_place_hold $< $@
	@xxd -c4 -p $@ > output/TEMP_FILE1
	@$(call CREATE_BIN,"spi_nor",$(BOOT_HEAD_NOR),$(BOOT_HEAD_LEN),1,"uni_app.bin")
	@$(CLEAN_TMP_FILE)
	@rm -rf tmp_objs

